﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace G.SL.Navigate
{
    public class NavigationContext
    {
        internal NavigationContext(Page page)
        {
            this.page = page;
        }

        public IDictionary<string, string> QueryString
        {
            get
            {
                return page.NavigationContext.QueryString;
            }
        }
        private object _param;
        /// <summary>
        /// 需要残递给新页面的参数，但是必须保证该参数可以被序列化
        /// </summary>
        public object Param
        {
            get
            {
                return _param;
            }
            set
            {
                _param = value;
            }
        }
        private Page page;
    }


    public class GBasePage : Page, INotifyPropertyChanged
    {
        /// <summary>
        /// 当程序处于后台时，导航的连接
        /// </summary>
        public const string APPExternal = @"app://external/";

        #region 静态数据
        private static object nextPageParam;
        private const string NavigationContext_ParamKeyName = "NavigationContext_Param";
        protected static NavigateBackFromEventArgs NavigateBackFromEventArgs;
        #endregion

        public new NavigationContext NavigationContext { get; private set; }
        public GBasePage()
        {
            this.NavigationContext = new NavigationContext(this);
        }

        protected bool Navigate(string uri, object param)
        {
            nextPageParam = param;
            return this.NavigationService.Navigate(new Uri(uri, UriKind.Relative));
        }

        ///// <summary>
        ///// 显示状态信息并设置状态栏背景
        ///// </summary>
        ///// <param name="msg"></param>
        //public void ShowState(string msg, Brush stateBackgroundBrush)
        //{
        //    PhoneApplicationPageHelp.ShowState(msg, TimeSpan.FromSeconds(4), stateBackgroundBrush, null);
        //}
        ///// <summary>
        ///// 显示状态信息
        ///// </summary>
        ///// <param name="msg"></param>
        //public void ShowState(string msg, Action callback = null)
        //{
        //    PhoneApplicationPageHelp.ShowState(msg, callback);
        //}
        /// <summary>
        /// 将参数从State中移除，主要是因为能够被存在State中的参数必须确保能够被序列化，否则使用后第一时间删除，不然会在墓碑以后出现crash
        /// 如果能够确保使用后能够马上删除的，那么在导航的时候可以传递任何类型的参数
        /// </summary>
        //protected void RemoveNagigateParam()
        //{
        //    if (this.NavigationContext.Param != null && this.State.ContainsKey(NavigationContext_ParamKeyName))
        //    {
        //        this.State.Remove(NavigationContext_ParamKeyName);
        //    }
        //}
        //private Uri selfUrl;


        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //selfUrl = e.Uri;

            if (nextPageParam != null)
            {
                this.NavigationContext.Param = nextPageParam;
                nextPageParam = null;
            }
            //this.State[NavigationContext_ParamKeyName] = this.NavigationContext.Param;
            //else if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
            //{
            //    if (this.NavigationContext.Param == null)
            //    {
            //        if (this.State.ContainsKey(NavigationContext_ParamKeyName))
            //        {
            //            this.NavigationContext.Param = this.State[NavigationContext_ParamKeyName];
            //        }
            //    }
            //}
            //CanUseState = true;
            base.OnNavigatedTo(e);
            //当从前一页返回到当前页的时候，将从前一页返回的数据添加到当前页
            //if (e.NavigationMode == NavigationMode.Back && NavigateBackFromEventArgs != null && NavigateBackFromEventArgs.HasHandle)
            //{
            //    OnNavigatingBackFrom(NavigateBackFromEventArgs);
            //    NavigateBackFromEventArgs = null;
            //}

        }
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {

            base.OnNavigatedFrom(e);
            //当从当前页返回到上一页的时候清空State中的数据
            //if (e.NavigationMode == NavigationMode.Back)
            //{
            //    //this.State.Clear();
            //    GC.Collect();//TODO:每次返回的时候调用一次内存清理，目前不知道这样做会不会影响性能，待测试
            //}
            //CanUseState = true;
        }

        //如果按了开始键，那个NavigatingCancelEventArgs的url=app://external/
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            base.OnNavigatingFrom(e);
            //当从当前页返回到前一页的时候，传递当前页的需要传递给前一页的参数，和OnNavigatedTo配合实现返回的时候回调的目的
            //if (e.NavigationMode == NavigationMode.Back)
            //{
            //    NavigateBackFromEventArgs = new NavigateBackFromEventArgs();
            //    NavigateBackFromEventArgs.From = this.GetType();
            //    OnNavigatingFromBack(NavigateBackFromEventArgs);
            //}
            //if (this.NavigatingFrom != null)
            //{
            //    this.NavigatingFrom(this, e);
            //}
            //CanUseState = false;
        }

        /// <summary>
        /// 从当前页返回到前一页的时候发生
        /// </summary>
        /// <param name="e">需要将数据返回给前一页处理，
        /// 如果有数据需要前一页处理的，
        /// 那么必须要将NavigateBackFromEventArgs的HasHandle设为True</param>
        //protected virtual void OnNavigatingFromBack(NavigateBackFromEventArgs e)
        //{
        //    //if (ViewModel != null)
        //    //    ViewModel.OnNavigatingFromBack_Internal(e);
        //}

        /// <summary>
        /// 从前一页返回到当前页的时候发生
        /// </summary>
        /// <param name="e">需要交给本页处理的数据</param>
        //protected virtual void OnNavigatingBackFrom(NavigateBackFromEventArgs e)
        //{
        //    //if (ViewModel != null)
        //    //    ViewModel.OnNavigatingBackFrom_Internal(e);
        //}

        /// <summary>
        /// 在页面即将不再是框架中的活动页面时调用
        /// </summary>
        public event NavigatingCancelHandler NavigatingFrom;

        //private bool canUseState;
        ///// <summary>
        ///// 是否可以使用State
        ///// </summary>
        //public bool CanUseState
        //{
        //    get
        //    {
        //        var page = PhoneApplicationPageHelp.GetBasePage();
        //        if (page == null || page != this)
        //            return false;
        //        return canUseState;
        //    }
        //    private set
        //    {
        //        canUseState = value;
        //    }
        //}

        //public void GoBack()
        //{
        //    if (!this.NavigationService.CanGoBack)
        //        return;
        //    foreach (var item in this.NavigationService.BackStack)
        //    {
        //        if (item.Source == this.NavigationService.Source || this.NavigationService.CurrentSource == this.selfUrl)
        //        {
        //            this.NavigationService.GoBack();
        //            break;
        //        }
        //    }
        //}

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
    public delegate void NavigatingCancelHandler(object sender, NavigatingCancelEventArgs e);
    /// <summary>
    /// 从前一页返回的时候需要回调的参数
    /// </summary>
    public class NavigateBackFromEventArgs : EventArgs
    {
        internal NavigateBackFromEventArgs()
        {

        }
        /// <summary>
        /// 指示是否需要处理
        /// </summary>
        public bool HasHandle { get; set; }
        /// <summary>
        /// 需要处理的数据
        /// </summary>
        public object Param { get; set; }


        public Type From { get; internal set; }
    }
}
